package com.lbb.http.provider

import android.os.Handler
import android.os.Looper
import android.util.Log
import com.lbb.http.bean.ResultException
import com.lbb.http.call.CallBack
import com.lbb.http.interceptor.ResultInterceptor
import com.lbb.http.log.OkHttpLog
import okhttp3.*
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.logging.HttpLoggingInterceptor
import java.io.IOException


class OkHttpProviderImpl private constructor() : OkHttpProvider {
    private val handler = Handler(Looper.getMainLooper())
    private val okHttpClient: OkHttpClient
    private val logInterceptor = HttpLoggingInterceptor(OkHttpLog())
    private var headers = mutableMapOf<String, String>()
    private var resultInterceptor: ResultInterceptor? = null

    init {
        logInterceptor.level = HttpLoggingInterceptor.Level.BODY
        okHttpClient = OkHttpClient.Builder().addNetworkInterceptor(logInterceptor).build()
    }

    companion object {
        private val JSON: MediaType = "application/json; charset=utf-8".toMediaType()

        // private val FORM: MediaType = "application/x-www-form-urlencoded".toMediaType()
        val instance: OkHttpProviderImpl by lazy(LazyThreadSafetyMode.SYNCHRONIZED) { OkHttpProviderImpl() }
    }

    override fun addHeader(key: String, value: String) {
        headers[key] = value
    }

    override fun setHeader(map: Map<String, String>) {
        headers.clear()
        headers = map as MutableMap<String, String>
    }

    override fun clearHeader() {
        headers.clear()
    }

    override fun setInterceptor(resultInterceptor: ResultInterceptor) {
        this.resultInterceptor = resultInterceptor
    }

    override fun addInterceptor(interceptor: Interceptor) {
        okHttpClient.newBuilder().addInterceptor(interceptor)
    }

    override fun get(url: String, map: Map<String, String>?, callback: CallBack<String>?) {
        val requestBuilder = Request.Builder()
        val httpUrlBuilder = url.toHttpUrl().newBuilder()
        for (header in headers) {
            requestBuilder.addHeader(header.key, header.value)
        }
        map?.let {
            for (item in it) {
                httpUrlBuilder.addQueryParameter(item.key, item.value)
            }
        }
        requestBuilder.url(httpUrlBuilder.build())
        val call: Call = okHttpClient.newCall(requestBuilder.build())
        call.enqueue(object : Callback {
            override fun onFailure(call: Call, e: IOException) {
                onFailure(e, callback)
            }

            override fun onResponse(call: Call, response: Response) {
                onResponse(response, callback)
            }

        })
    }

    override fun postForm(url: String, map: Map<String, String>?, callback: CallBack<String>?) {
//        val requestBody = map.toString().toRequestBody(FORM)
        val requestBuilder = Request.Builder()
        for (header in headers) {
            requestBuilder.addHeader(header.key, header.value)
        }
        val formBodyBuilder: FormBody.Builder = FormBody.Builder()
        map?.let {
            for (item in map) {
                formBodyBuilder.add(item.key, item.value)
            }
        }
        requestBuilder.url(url)
        requestBuilder.post(formBodyBuilder.build())
        val call: Call = okHttpClient.newCall(requestBuilder.build())
        call.enqueue(object : Callback {
            override fun onFailure(call: Call, e: IOException) {
                onFailure(e, callback)
            }

            override fun onResponse(call: Call, response: Response) {
                onResponse(response, callback)
            }
        })

    }

    override fun postJson(url: String, map: Map<String, String>?, callback: CallBack<String>?) {
        val requestBody = map.toString().toRequestBody(JSON)
        val requestBuilder = Request.Builder()
        for (header in headers) {
            requestBuilder.addHeader(header.key, header.value)
        }
        requestBuilder.url(url)
        requestBuilder.post(requestBody)
        val call: Call = okHttpClient.newCall(requestBuilder.build())
        call.enqueue(object : Callback {
            override fun onFailure(call: Call, e: IOException) {
                onFailure(e, callback)
            }

            override fun onResponse(call: Call, response: Response) {
                onResponse(response, callback)
            }
        })
    }

    private fun onResponse(response: Response, callback: CallBack<String>?) {
        try {
            if (response.isSuccessful) {
                var string: String = response.body?.string().toString()
                if (resultInterceptor != null) {
                    string = resultInterceptor?.onResponse(string).toString()
                }
                handler.post {
                    callback?.success(string)
                    callback?.complete()
                }
                return
            }
            handler.post {
                callback?.error("服务器异常")
                callback?.complete()
            }
        } catch (e: ResultException) {
            handler.post {
                callback?.error(e.message.toString())
                callback?.complete()
            }
        } catch (e: Exception) {
            handler.post {
                callback?.error(e.message.toString())
                callback?.complete()
            }
        }
    }

    private fun onFailure(e: IOException, callback: CallBack<String>?) {
        Log.i("http", "onFailure-->" + e.message.toString())
        handler.post {
            callback?.error("服务器异常")
            callback?.complete()
        }
    }
}